﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ServiceModel.Syndication;
using System.Text.RegularExpressions;
using Microsoft.Phone.Tasks;
using AgiliTrain.PhoneyTools;

namespace GooNews.ViewModels
{
  /// <summary>
  /// 
  /// </summary>
  public class FeedItem : ObservableObject
  {
    /// <summary>
    /// Initializes a new instance of the <see cref="FeedItem"/> class.
    /// </summary>
    public FeedItem()
    {

    }

    /// <summary>
    /// Initializes a new instance of the <see cref="FeedItem"/> class.
    /// </summary>
    /// <param name="item">The item.</param>
    public FeedItem(SyndicationItem item)
    {
      DatePublished = item.PublishDate.UtcDateTime;
      Title = item.Title.Text;
      Link = item.Links.Count == 0 ? null : item.Links[0].Uri.AbsoluteUri;
      Summary = item.Summary.Text;
      ParseSummary(item.Summary);
    }

    /// <summary>
    /// Parses the summary.
    /// </summary>
    /// <param name="summary">The summary.</param>
    private void ParseSummary(TextSyndicationContent summary)
    {
      var html = summary.Text;
      var imageEx = new Regex("<img[^>]* src=\"([^\"]*)\"[^>]*>", RegexOptions.IgnoreCase);
      if (imageEx.IsMatch(html))
      {
        var match = imageEx.Match(html);
        if (match.Groups.Count > 1)
        {
          ImageUrl = match.Groups[1].Value;
          HasImageUrl = true;
        }
      }

      var titleEx = new Regex("<b>([^<]*)</b>", RegexOptions.IgnoreCase);
      if (titleEx.IsMatch(html))
      {
        var match = titleEx.Match(html);
        if (match.Groups.Count > 0)
        {
          var val = match.Groups[0].Value;
          if (val.Length > (Title.Length / 2) + 7)
          {
            Title = HttpUtility.HtmlDecode(val.Substring(3, val.Length - 7));
          }
        }
      }
    }

    /// <summary>
    /// Calculates the published since.
    /// </summary>
    private void CalculatePublishedSince()
    {
      var span = DateTime.Now.ToUniversalTime() - DatePublished;
      if (span.TotalHours < 1)
      {
        var minutes = Math.Floor(span.TotalMinutes);
        PublishedSince = string.Concat(minutes, minutes == 1 ? " minute ago" : " minutes ago");
      }
      else if (span.TotalDays < 1)
      {
        var hours = Math.Floor(span.TotalHours);
        PublishedSince = string.Concat(hours, hours == 1 ? " hour ago" : " hours ago");
      }
      else
      {
        var days = Math.Floor(span.TotalDays);
        PublishedSince = string.Concat(days, days == 1 ? " day ago" : " days ago");
      }
    }

    DateTime _datePublished;

    /// <summary>
    /// Gets or sets the date published.
    /// </summary>
    /// <value>
    /// The date published.
    /// </value>
    public DateTime DatePublished
    {
      get { return _datePublished; }
      set
      {
        _datePublished = value;
        CalculatePublishedSince();
        RaisePropertyChanged("DatePublished");
      }
    }

    string _title;

    /// <summary>
    /// Gets or sets the title.
    /// </summary>
    /// <value>
    /// The title.
    /// </value>
    public string Title
    {
      get { return _title; }
      set
      {
        _title = value;
        RaisePropertyChanged("Title");
      }
    }

    string _link;

    /// <summary>
    /// Gets or sets the link.
    /// </summary>
    /// <value>
    /// The link.
    /// </value>
    public string Link
    {
      get { return _link; }
      set
      {
        _link = value;
        RaisePropertyChanged("Link");
      }
    }

    bool _hasImageUrl = false;

    /// <summary>
    /// Gets or sets a value indicating whether this instance has image URL.
    /// </summary>
    /// <value>
    /// 	<c>true</c> if this instance has image URL; otherwise, <c>false</c>.
    /// </value>
    public bool HasImageUrl
    {
      get { return _hasImageUrl; }
      set
      {
        _hasImageUrl = value;
        RaisePropertyChanged("HasImageUrl");
      }
    }


    string _imageUrl;

    /// <summary>
    /// Gets or sets the image URL.
    /// </summary>
    /// <value>
    /// The image URL.
    /// </value>
    public string ImageUrl
    {
      get { return _imageUrl; }
      set
      {
        _imageUrl = value;
        RaisePropertyChanged("ImageUrl");
      }
    }

    string _publishedSince;

    /// <summary>
    /// Gets or sets the published since.
    /// </summary>
    /// <value>
    /// The published since.
    /// </value>
    public string PublishedSince
    {
      get { return _publishedSince; }
      set
      {
        _publishedSince = value;
        RaisePropertyChanged("PublishedSince");

      }
    }

    string _publication;

    /// <summary>
    /// Gets or sets the publication.
    /// </summary>
    /// <value>
    /// The publication.
    /// </value>
    public string Publication
    {
      get { return _publication; }
      set
      {
        _publication = value;
        RaisePropertyChanged("Publication");
      }
    }

    string _summary;

    /// <summary>
    /// Gets or sets the summary.
    /// </summary>
    /// <value>
    /// The summary.
    /// </value>
    public string Summary
    {
      get { return _summary; }
      set
      {
        _summary = value;
        RaisePropertyChanged("Summary");
      }
    }

    /// <summary>
    /// Sends to insta paper.
    /// </summary>
    /// <param name="withUri">The with URI.</param>
    /// <param name="callback">The callback.</param>
    public void SendToInstaPaper(string withUri, Action<bool> callback)
    {
      
      string ipLink = string.Format("https://www.instapaper.com/api/add?username={0}&password={1}&url={2}&title={3}",
        HttpUtility.UrlEncode(App.ViewModel.Options.InstaPaperUserName),
        HttpUtility.UrlEncode(App.ViewModel.Options.InstaPaperPassword),
        HttpUtility.UrlEncode(withUri),
        HttpUtility.UrlEncode(Title));

      var client = new WebClient();
      client.DownloadStringCompleted += (s, a) =>
      {
        if (!a.Cancelled && a.Error == null)
        {
          callback(true);
        }
        else
        {
          callback(false);
        }
      };
      client.DownloadStringAsync(new Uri(ipLink));

    }

    /// <summary>
    /// Sends to insta paper.
    /// </summary>
    /// <param name="callback">The callback.</param>
    public void SendToInstaPaper(Action<bool> callback)
    {
      SendToInstaPaper(this.Link, callback);
    }

    /// <summary>
    /// Sends to email.
    /// </summary>
    public void SendToEmail()
    {
      SendToEmail(this.Link);
    }

    /// <summary>
    /// Sends to email.
    /// </summary>
    /// <param name="uri">The URI.</param>
    public void SendToEmail(string uri)
    {
      new EmailComposeTask()
      {
        Subject = Title,
        Body = string.Concat("I found this great article on GooNews (on my Windows Phone 7 device):",
          Environment.NewLine,
          Environment.NewLine,
          uri)
      }.Show();
    }
  }
}